﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Text.RegularExpressions;
using System.Reflection;
using System.IO;
using System.Collections.Generic;
using System.Linq;

namespace WebSiteAdminTool.UI.Utils
{
    public class PageUriLocator
    {
        public static string GetUri<T>() where T : Page
        {
            var typeName = typeof(T).Name;

            var allXamlFiles = ReadAssemblyResource();

            var fileName = new Regex(@"[[\w]*/]?" + typeName.ToLower() + @"\.xaml");
            return (allXamlFiles.Where(xamlFile => fileName.IsMatch(xamlFile.ToLower()))
                                .Select(xamlFile => xamlFile))
                                .FirstOrDefault();
        }

        private static IEnumerable<string> ReadAssemblyResource()
        {
            byte[] binaryData = GetResourceInByteArray();
            var fileNames = new List<string>();

            // the first x bytes of the resource stream we are not interested in
            bool start = false;
            for (int i = 0; i < binaryData.Length; i++)
            {
                if (i < binaryData.Length - 255 && i > 0)
                {
                    // the first file in the resource stream is app.xaml => it is 00 00 10 in size
                    start = start | (binaryData[i] == 0x00 && binaryData[i + 1] == 0x00 && binaryData[i + 2] == 0x10);
                    if (start)
                    {
                        int length = binaryData[i + 1] + binaryData[i + 2]; // the length is described in the two latter bytes of the 5 stopbytes
                        if (length > 255) return fileNames; // name cannot be longer then 255 characters

                        // assemble the filename
                        string fileName = "";

                        for (int j = 0; j < length; j += 2)
                        {
                            fileName += Convert.ToChar(binaryData[j + i + 3]);
                        }

                        fileNames.Add(fileName);
                        i += length + 4;
                    }
                }
            }

            return fileNames;
        }

        private static byte[] GetResourceInByteArray()
        {
            // get the assembly name
            var assemblyName = Assembly.GetExecutingAssembly().FullName.Split(',')[0];

            // a list of resources is saved in an embedded resource file called [AssemblyName].g.resources
            var resourceName = assemblyName + ".g.resources";

            // read binary data from the stream
            var resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);
            var streamReader = new BinaryReader(resourceStream);
            return streamReader.ReadBytes((int)resourceStream.Length);
        }
    }
}
